package com.secxiot.consumer.user.controller;

import cn.hutool.crypto.SecureUtil;
import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jiguang.common.utils.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.secxiot.common.constant.ServerStatusEnum;
import com.secxiot.common.entity.ResultVo;
import com.secxiot.common.exception.BaseException;
import com.secxiot.common.utils.CachedBeanCopier;
import com.secxiot.common.utils.ClientUnit;
import com.secxiot.common.utils.JSMSUtil;
import com.secxiot.common.utils.RedisUtil;
import com.secxiot.consumer.user.feign.UserClient;
import com.secxiot.provider.system.dto.FileLogDto;
import com.secxiot.provider.user.dto.DeptDto;
import com.secxiot.provider.user.dto.UserDeptDto;
import com.secxiot.provider.user.dto.UserDto;
import com.secxiot.provider.user.entity.UserDo;
import com.secxiot.provider.user.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

@Api(tags = "登录注册相关")
@RequestMapping("login")
@RestController
public class LoginController {
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private UserClient userClient;
    private final static String USER_TYPE = "0000100001";

    @ApiOperation(value = "用户注册", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "用户类型，字典", paramType = "form", required = true),
            @ApiImplicitParam(name = "mobile", value = "手机号", paramType = "form", required = true),
            @ApiImplicitParam(name = "code", value = "验证码", paramType = "form", required = true),
            @ApiImplicitParam(name = "password", value = "密码", paramType = "form", required = true),
            @ApiImplicitParam(name = "name", value = "姓名", paramType = "form", required = true),
            @ApiImplicitParam(name = "liveAddress", value = "地址", paramType = "form", required = false),
            @ApiImplicitParam(name = "picId", value = "头像id", paramType = "form", required = false, dataType = "Long"),
            @ApiImplicitParam(name = "deptId", value = "医院部门id", paramType = "form", required = false, dataType = "Long")
    })
    @PostMapping("/registry")
    public ResultVo<UserVo> registry(
            @RequestParam(value = "type", required = true) String type,
            @RequestParam(value = "mobile", required = true) String mobile,
            @RequestParam(value = "code", required = true) String code,
            @RequestParam(value = "password", required = true) String password,
            @RequestParam(value = "liveAddress", required = false) String liveAddress,
            @RequestParam(value = "name", required = true) String name,
            @RequestParam(value = "picId", required = false) Long picId,
            @RequestParam(value = "deptId", required = false) Long deptId,
            HttpServletRequest request) throws BaseException, APIConnectionException, APIRequestException {
        // 校验code
        if (!JSMSUtil.sendValidSMSCode(mobile, code)) {
            return new ResultVo<UserVo>(ServerStatusEnum.VALID_SMS_CODE_ERROR);
        }

        //判断选择非患者时验证职业所属医院是否为空
        if (!USER_TYPE.equals(type) && null == deptId) {
            return new ResultVo<UserVo>(ServerStatusEnum.TYPE_NOTHOS);
        }

        UserDto userDto = UserDto.builder()
                .type(type)
                .mobile(mobile)
                .username(mobile)
                .password(SecureUtil.md5(password))
                //.identificationNumber(identificationNumber)
                .name(name)
                .liveAddress(liveAddress)
                //.birth(IdcardUtil.getBirthDate(identificationNumber))
                //.sex(IdcardUtil.getGenderByIdCard(identificationNumber))
                .picId(picId)
                .hospitalId(deptId)
                .deptId(deptId)
                .build();
        UserDo user = userClient.registry(userDto);
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user, userVo);
        userVo.setStatus(user.getStatus().intValue());
        userVo.setSex(user.getSex());
        /* DeptDto dept = userClient.getDeptByUserId(user.getUserId());*/
       /* if (dept != null) {
            userVo.setDeptName(dept.getName());
            userVo.setDeptId(dept.getDeptId());
        }*/
        if (user.getPicId() != null) {
            FileLogDto fileUri = userClient.getFileUri(user.getPicId());
            if (fileUri != null) {
                userVo.setHeaderImg(fileUri.getFileUri());
            }
        }
        return new ResultVo<UserVo>(userVo);
    }

    @ApiOperation(value = "用户登录", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", paramType = "form", required = true),
            @ApiImplicitParam(name = "password", value = "密码", paramType = "form", required = true)
    })
    @PostMapping
    public ResultVo<UserVo> login(
            @RequestParam(value = "username", required = true) String username,
            @RequestParam(value = "password", required = true) String password,
            HttpServletRequest request) {

        UserDo userDo = userClient.getUserByPhone(username, ClientUnit.CLIENT_TYPE_APP);
        // 登录校验
        if (userDo == null) {
            return new ResultVo<UserVo>(ServerStatusEnum.NOT_FOUND);
        }
        String md5 = SecureUtil.md5(password);
        if (userDo.getPassword().equalsIgnoreCase(md5)) {
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(userDo, userVo);
            userVo.setStatus(userDo.getStatus().intValue());
            userVo.setSex(userDo.getSex());
            DeptDto dept = userClient.getDeptByUserId(userDo.getUserId());
            if (dept != null) {
                userVo.setDeptName(dept.getName());
                userVo.setDeptId(dept.getDeptId());
            }
            FileLogDto fileUri = userClient.getFileUri(userDo.getPicId());
            if (fileUri != null) {
                userVo.setHeaderImg(fileUri.getFileUri());
            }
            if (!"0000100001".equals(userDo.getType())) {
                List<UserDeptDto> userDeptDtos = userClient.listSupperDeptByUserId(userDo.getUserId());
                List<DeptVo> supperDepts = new ArrayList<>();
                for (UserDeptDto d : userDeptDtos) {
                    DeptVo deptVo = new DeptVo();
                    CachedBeanCopier.copy(d, deptVo);
                    supperDepts.add(deptVo);
                }
                userVo.setSupperDepts(supperDepts);
            } else {
                userVo.setUserEmergencyContact(userClient.getContact(userDo.getUserId()));
            }

            String key = "LOGIN_" + userVo.getUserId();
            String loginCode = getRandomNickname(10);
            redisUtil.set(key, "111111");
            userVo.setLoginCode("111111");
            return new ResultVo<UserVo>(userVo);
        } else {
            return new ResultVo<UserVo>(ServerStatusEnum.LOGIN_FAIL);
        }
    }

    @ApiOperation(value = "退出登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", required = true, dataType = "Long", paramType = "query")
    })
    @DeleteMapping("")
    public ResultVo<String> getUser(@RequestParam(value = "userId", required = true) Long userId) {
        // TODO 退出登录
        UserVo userVo = new UserVo();
        return new ResultVo<>("SUCCESS");
    }

    @ApiOperation(value = "用户注册（药品追踪记录微信小程序）", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "用户类型，字典", paramType = "form", required = true),
            @ApiImplicitParam(name = "mobile", value = "手机号", paramType = "form", required = true),
            @ApiImplicitParam(name = "code", value = "验证码", paramType = "form", required = true),
            @ApiImplicitParam(name = "name", value = "微信昵称", paramType = "form", required = true),
            @ApiImplicitParam(name = "hospitalId", value = "医疗机构ID", paramType = "form", required = false, dataType = "Long"),
            @ApiImplicitParam(name = "wxOpenid", value = "微信唯一标识", paramType = "form", required = true),
            @ApiImplicitParam(name = "wxUserid", value = "微信用户唯一标识", paramType = "form", required = false),
            @ApiImplicitParam(name = "picId", value = "用户头像", paramType = "form", required = false, dataType = "String"),
    })
    @PostMapping("/narcoticRegistry")
    public ResultVo<UserNarcoticVo> narcoticRegistry(
            @RequestParam(value = "type", required = true) String type,
            @RequestParam(value = "mobile", required = true) String mobile,
            @RequestParam(value = "code", required = true) String code,
            @RequestParam(value = "name", required = true) String name,
            @RequestParam(value = "hospitalId", required = false) Long hospitalId,
            @RequestParam(value = "wxOpenid", required = true) String wxOpenid,
            @RequestParam(value = "wxUserid", required = false) String wxUserid,
            @RequestParam(value = "picId", required = false) String picId,
            HttpServletRequest request) throws BaseException, APIConnectionException, APIRequestException {

        UserNarcoticVo userNarcoticVo = new UserNarcoticVo();
        List<DeptVo> supperDepts = new ArrayList<>();

        // 校验code
        if (!JSMSUtil.sendValidSMSCode(mobile, code)) {
            return new ResultVo<UserNarcoticVo>(ServerStatusEnum.VALID_SMS_CODE_ERROR);
        }

        //判断 患者 医生 药师 监管
        if ("".equals(type)) {
            return new ResultVo<UserNarcoticVo>(ServerStatusEnum.NARCOTIC_DRUGS_TYPE_EMPTY);
        }

        if ("".equals(wxOpenid) || "undefined".equals(wxOpenid)) {
            return new ResultVo<UserNarcoticVo>(ServerStatusEnum.NARCOTIC_WXOPENID);
        }
        String wxHeadImg = "";
        try {
            if (StringUtils.isNotEmpty(picId)) {
                wxHeadImg = URLDecoder.decode(picId, "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        UserDto userDto = UserDto.builder()
                .type(type)
                .mobile(mobile)
                .username(mobile)
                .name(name)
                .hospitalId(hospitalId)
                .wxOpenid(wxOpenid)
                .wxUserid(wxUserid)
                .wxHeadImg(wxHeadImg)
                .build();
        UserDo user = userClient.narcoticRegistry(userDto);

        CachedBeanCopier.copy(user, userNarcoticVo);
        userNarcoticVo.setStatus(user.getStatus());
        userNarcoticVo.setSex(user.getSex());

        DeptDto dept = userClient.getDeptByUserId(user.getUserId());
        if (dept != null) {
            userNarcoticVo.setDeptName(dept.getName());
            userNarcoticVo.setDeptId(dept.getDeptId());
        }
        //获取用户部门信息
        List<UserDeptDto> userDeptDtos = userClient.listSupperDeptByUserId(user.getUserId());
        if (!userDeptDtos.isEmpty()) {
            supperDepts = userDeptDtos.stream().map(p -> {
                DeptVo deptVo = new DeptVo();
                CachedBeanCopier.copy(p, deptVo);
                return deptVo;
            }).collect(Collectors.toList());
        }
        userNarcoticVo.setSupperDepts(supperDepts);
        //获取头像
//        if (user.getPicId() != null) {
//            FileLogDto fileUri = userClient.getFileUri(user.getPicId());
//            if (fileUri != null) {
//                userNarcoticVo.setHeaderImg(fileUri.getFileUri());
//            }
//        }
        if (userNarcoticVo.getHospitalId() != null) {
            HospitalVo hospitalVo = userClient.getHospitalById(userNarcoticVo.getHospitalId());
            if (hospitalVo != null) {
                userNarcoticVo.setHospitalName(hospitalVo.getHospitalName());
                userNarcoticVo.setHospitalAddress(hospitalVo.getAddress());
            }
        }
        userNarcoticVo.setHeaderImg(wxHeadImg);
        return new ResultVo<UserNarcoticVo>(userNarcoticVo);
    }

    @ApiOperation(value = "用户注册（SOS微信小程序）", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "注册类型 0 微信注册  1 手机号", paramType = "form", required = true),
            @ApiImplicitParam(name = "mobile", value = "手机号", paramType = "form", required = true),
            @ApiImplicitParam(name = "code", value = "验证码", paramType = "form", required = false),
            @ApiImplicitParam(name = "name", value = "微信昵称", paramType = "form", required = true),
            @ApiImplicitParam(name = "wxOpenid", value = "微信唯一标识", paramType = "form", required = true),
            @ApiImplicitParam(name = "wxUserid", value = "微信用户唯一标识", paramType = "form", required = false),
            @ApiImplicitParam(name = "wxHeadImg", value = "用户头像", paramType = "form", required = false),
            @ApiImplicitParam(name = "province", value = "地址省份", paramType = "form", required = false),
            @ApiImplicitParam(name = "city", value = "地址城市", paramType = "form", required = false),
            @ApiImplicitParam(name = "wxAppId", value = "微信ID", paramType = "form", required = false),
            @ApiImplicitParam(name = "promoteCode", value = "邀请码", paramType = "form", required = false),
            @ApiImplicitParam(name = "locationProvince", value = "注册位置-省", paramType = "form", required = false),
            @ApiImplicitParam(name = "locationCity", value = "注册位置-城市", paramType = "form", required = false),
            @ApiImplicitParam(name = "locationDistrict", value = "注册位置-区域", paramType = "form", required = false)
    })
    @PostMapping("/sosRegistry")
    public ResultVo<UserSosVo> sosRegistry(
            @RequestParam(value = "type", required = true) String type,
            @RequestParam(value = "mobile", required = true) String mobile,
            @RequestParam(value = "code", required = false) String code,
            @RequestParam(value = "name", required = true) String name,
            @RequestParam(value = "wxOpenid", required = true) String wxOpenid,
            @RequestParam(value = "wxUserid", required = false) String wxUserid,
            @RequestParam(value = "wxHeadImg", required = false) String wxHeadImg,
            @RequestParam(value = "province", required = false) String province,
            @RequestParam(value = "city", required = false) String city,
            @RequestParam(value = "wxAppId", required = false) String wxAppId,
            @RequestParam(value = "promoteCode", required = false) String promoteCode,
            @RequestParam(value = "locationProvince", required = false) String locationProvince,
            @RequestParam(value = "locationCity", required = false) String locationCity,
            @RequestParam(value = "locationDistrict", required = false) String locationDistrict,
            HttpServletRequest request) throws BaseException, APIConnectionException, APIRequestException {
        UserSosVo userSosVo = new UserSosVo();
        //手机号注册
        if ("1".equals(type)) {
            // 校验code
            if (!JSMSUtil.sendValidSMSCode(mobile, code)) {
                return new ResultVo<UserSosVo>(ServerStatusEnum.VALID_SMS_CODE_ERROR);
            }
        }
        if ("".equals(wxOpenid) || "undefined".equals(wxOpenid)) {
            return new ResultVo<UserSosVo>(ServerStatusEnum.NARCOTIC_WXOPENID);
        }
        /*String wxHeadImg = "";
        try {
            if (StringUtils.isNotEmpty(picId)) {
                wxHeadImg = URLDecoder.decode(picId, "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        UserDto userDto = UserDto.builder()
                .type(USER_TYPE)
                .mobile(mobile)
                .username(mobile)
                .name(name)
                .wxOpenid(wxOpenid)
                .wxUserid(wxUserid)
                .wxHeadImg(wxHeadImg)
                .province(province)
                .city(city)
                .promoteCode(promoteCode)
                .locationProvince(locationProvince)
                .locationCity(locationCity)
                .locationDistrict(locationDistrict)
                .build();
        if(StringUtils.isNotEmpty(wxAppId)){
            userDto.setWxAppId(wxAppId);
        }
        UserDo user = userClient.sosRegistry(userDto);

        CachedBeanCopier.copy(user, userSosVo);
        userSosVo.setSex(user.getSex());
        userSosVo.setHeaderImg(wxHeadImg);
        return new ResultVo<UserSosVo>(userSosVo);
    }

    @ApiOperation(value = "用户登录状态判断", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", required = true, paramType = "query", dataType = "Long")
    })
    @PostMapping("/getLoginStatus")
    public ResultVo<String> getEscortCarLocation(@RequestParam(value = "userId", required = true) Long userId) throws BaseException {
        JSONObject obj = new JSONObject();
        Object object = redisUtil.get("LOGIN_" + userId);
        return new ResultVo<String>(object.toString());
    }

    /**
     * java生成随机数字10位数
     * @param length length[生成随机数的长度]
     * @return
     */
    public static String getRandomNickname(int length) {
        String val = "";
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            val += String.valueOf(random.nextInt(10));
        }
        return val;
    }
}
